package com.deer.wms.ASN.manage.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.deer.wms.ASN.manage.constant.AsnManageConstant;
import com.deer.wms.ASN.manage.dao.QcRecordMapper;
import com.deer.wms.ASN.manage.model.in.AcceptRecord;
import com.deer.wms.ASN.manage.model.qc.*;
import com.deer.wms.ASN.manage.service.AcceptRecordService;
import com.deer.wms.ASN.manage.service.QcRecordFileService;
import com.deer.wms.ASN.manage.service.QcRecordService;
import com.deer.wms.busine.tactic.model.PrintTempInfo;
import com.deer.wms.busine.tactic.service.PrintTempInfoService;
import com.deer.wms.busine.tactic.service.PrintTempUtils;
import com.deer.wms.intercept.common.data.CurrentUser;
import com.deer.wms.inventory.constant.InventoryConstant;
import com.deer.wms.inventory.dao.InventoryMapper;
import com.deer.wms.inventory.model.Inventory.Inventory;
import com.deer.wms.inventory.model.Inventory.InventoryTransact;
import com.deer.wms.inventory.service.InventoryService;
import com.deer.wms.inventory.service.InventoryTransactService;
import com.deer.wms.project.root.core.result.CommonCode;
import com.deer.wms.project.root.exception.ServiceException;
import com.deer.wms.project.root.service.SuperServiceImpl;
import com.deer.wms.project.root.util.BeanUtils;
import com.deer.wms.project.root.util.DateUtils;
import com.deer.wms.system.manage.constant.SystemManageConstant;
import com.deer.wms.system.manage.service.CodeRuleService;
import com.deer.wms.ware.task.service.PushErpService;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.deer.wms.project.root.util.CollectionUtils.convertMap;

/**
 * @author guo
 * @since 2020/01/15
 */
@Service
@Transactional
@Slf4j
public class QcRecordServiceImpl extends SuperServiceImpl<QcRecordMapper, QcRecord> implements QcRecordService {

    @Autowired
    private QcRecordMapper qcRecordMapper;
    @Autowired
    private QcRecordService qcRecordService;
    @Autowired
    private QcRecordFileService qcRecordFileService;
    @Autowired
    private AcceptRecordService acceptRecordService;
    @Autowired
    private CodeRuleService codeRuleService;
    @Autowired
    private InventoryTransactService inventoryTransactService;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private InventoryMapper inventoryMapper;

    @Autowired
    private PushErpService pushErpService;

    @Override
    public List<QcRecordDto> findList(QcRecordCriteria criteria) {
        return qcRecordMapper.findList(criteria);
    }

    /**
     * 归档
     *
     * @param detailNo
     * @param currentUser
     */
    @Override
    public void createFile(String detailNo, CurrentUser currentUser) {
        QcRecord qcRecord = qcRecordService.getOneByField("detail_no", detailNo);

        Integer fileUserId = currentUser.getUserId();
        String fileUserName = currentUser.getUserName();
        String fileTime = DateUtils.getNowDateTimeString();

        QcRecordFile qcRecordFile = new QcRecordFile();
        BeanUtils.copyProperties(qcRecordFile, qcRecord);

        qcRecordFile.setCreateUserId(fileUserId);
        qcRecordFile.setCreateUserName(fileUserName);
        qcRecordFile.setCreateTime(fileTime);

        qcRecordFileService.save(qcRecordFile);
        qcRecordService.deleteByDetailNo(detailNo);
    }

    @Override
    public void deleteByDetailNo(String detailNo) {
        qcRecordMapper.deleteByDetailNo(detailNo);
    }

    @Override
    public QcRecord qcResult(QcResultCriteria criteria, CurrentUser currentUser) {
        //Step1.根据收货单生成质检单
        AcceptRecord acceptRecord = acceptRecordService.getOneByField("accept_record_code", criteria.getBillCode());


        QcRecord qcRecord = processQcData(acceptRecord);
        qcRecord.setAsnBillNo(acceptRecord.getAsnBillNo());




        qcRecord.setQcRecordCode(codeRuleService.generateCode(SystemManageConstant.CORE_RULE_QC));
        // 设置合格，不合格，让步数量 质检结果 质检时间
        qcRecord.setQualifiedQuantity(criteria.getQualifiedQuantity());
        qcRecord.setRemake(criteria.getRemake());
        qcRecord.setFiedQuantity(criteria.getFiedQuantity());
        qcRecord.setConcessionQuantity(criteria.getConcessionQuantity());
        qcRecord.setQcQuantity(criteria.getQcQuantity());
        qcRecord.setConcessionAcceptId(criteria.getConcessionAcceptId());
        qcRecord.setQualityAbnormalId(criteria.getQualityAbnormalId());

        // 设置实检数量,操作员,质检结果，质检时间
//        qcRecord.setRealQuantity(acceptRecord.getQuantity());
        qcRecord.setRealQuantity(criteria.getQcQuantity());
        qcRecord.setQcUserId(currentUser.getUserId());
        qcRecord.setQcUserName(currentUser.getUserName());


        if (criteria.getQcResult() == null) {
            // 这里增加一层判断 如果前台没有质检结果 我们根据数量再次进行结果判断
            //检验结果(0-不合格 1-合格 2-让步)
            if (criteria.getFiedQuantity() > 0) {
                // 不合格
                criteria.setQcResult(0);
            } else if (criteria.getQualifiedQuantity() > criteria.getConcessionQuantity()) {
                // 合格
                criteria.setQcResult(1);
            } else {
                // 让步
                criteria.setQcResult(2);
            }
        }
        qcRecord.setQcResult(criteria.getQcResult());
        qcRecord.setQcTime(DateUtil.now());
        qcRecord.setQcBillNo(acceptRecord.getAsnDetailNo());

        qcRecordService.save(qcRecord);


        //Step2.生成库存事务
        InventoryTransact inventoryTransact = toStockRequest(qcRecord, criteria.getQcResult());


        // list 改为一条数据
        Inventory inventory = inventoryMapper.selectById(acceptRecord.getInventoryId());

        // 新增逻辑--质检不合格后的库存扣减情况
        // 获取质检单的不合格数量
        Double unQty = qcRecord.getFiedQuantity();

        // 库存冻结数量扣减为 质检单 三个数量的和
        Double allQty = qcRecord.getQualifiedQuantity() + qcRecord.getConcessionQuantity() + unQty;
        inventory.setState(InventoryConstant.TRANSACT_STATE_NORMAL);
        inventory.setFreezeQuantity(inventory.getFreezeQuantity() - allQty);
        // 判断不合格数量是否大于0 ， 大于0则扣减对应库存的总数量
        if (unQty > 0) {
            inventory.setQuantity(inventory.getQuantity() - unQty);
        }
        inventory.setStateDis(null);
        // 库存更新
        inventoryService.saveOrUpdate(inventory);

        if (inventory.getQuantity() <= 0) {
            inventoryService.removeById(inventory);
        }


        //Step3.更新收货单的质检状态
        // 原业务逻辑
//        if (AsnManageConstant.QC_RESULT_UNQ.equals(criteria.getQcResult())) {
//            //不合格 继续冻结 记录原因
//            acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_CHECKED_FAIL);
//        } else if (AsnManageConstant.QC_RESULT_QUA.equals(criteria.getQcResult())) {
//            acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_CHECKED_PASS);
//        } else {
//            acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_CHECKED_CON);
//        }
        // 新业务逻辑
        // 记录收货单 合格数量（合格+让步）与 不合格数量（不合格数量）
        // 根据质检的合格+让步数量来判断质检状态, 合格+让步>0就是合格 反之就是不合格
        if (qcRecord.getQualifiedQuantity() + qcRecord.getConcessionQuantity() > 0) {
            acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_CHECKED_PASS);
            acceptRecord.setQcQuantity(acceptRecord.getQcQuantity()+qcRecord.getQcQuantity());
            // 收货单合格数量
            acceptRecord.setQualifiedQuantity(acceptRecord.getQualifiedQuantity()+qcRecord.getQualifiedQuantity() + qcRecord.getConcessionQuantity());
            // 收货单不合格数量
            acceptRecord.setUnqualifiedQuantity(acceptRecord.getUnqualifiedQuantity()+qcRecord.getFiedQuantity());
        } else {
            // 全部都是不合格的
            acceptRecord.setQcQuantity(acceptRecord.getQcQuantity()+qcRecord.getQcQuantity());
            // 收货单合格数量
            acceptRecord.setQcState(AsnManageConstant.ACCEPT_QC_STATE_CHECKED_FAIL);
            // 收货单不合格数量
            acceptRecord.setUnqualifiedQuantity(acceptRecord.getUnqualifiedQuantity()+qcRecord.getFiedQuantity());
        }

        acceptRecordService.updateById(acceptRecord);

        return qcRecord;
    }

    /**
     * 质检回传
     *
     * @param qcRecord
     * @param currentUser
     */
    @Override
    @Transactional
    public void submit(QcRecord qcRecord, CurrentUser currentUser) {
        //获取异常单号
        if (ObjectUtil.isNotEmpty(qcRecord.getAbnormalBillNo())) {
            qcRecord.setQualityAbnormalId(pushErpService.findException(qcRecord.getAbnormalBillNo()));
        }
        if (qcRecord.getConcessionQuantity() > 0 && ObjectUtil.isEmpty(qcRecord.getEspeciallyBillNo())) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "请录入 特采单号");
        }
        //获取特采单号
        if (ObjectUtil.isNotEmpty(qcRecord.getEspeciallyBillNo())) {
            qcRecord.setConcessionAcceptId(pushErpService.findSpecial(qcRecord.getEspeciallyBillNo()));
            log.info("特采单号{}\n<<<<-特采单id{}\n>>>>", qcRecord.getEspeciallyBillNo(), qcRecord.getConcessionAcceptId());
        }

        QcResultCriteria qcResultCriteria = new QcResultCriteria();
        qcResultCriteria.setConcessionAcceptId(qcRecord.getConcessionAcceptId());
        qcResultCriteria.setQualityAbnormalId(qcRecord.getQualityAbnormalId());

        qcResultCriteria.setBillCode(qcRecord.getAcceptRecordCode());
        qcResultCriteria.setQcResult(qcRecord.getQcResult());
        //质检数量
        qcResultCriteria.setQcQuantity(qcRecord.getAchieveQuantity());
        //合格数量
        qcResultCriteria.setQualifiedQuantity(qcRecord.getQualifiedQuantity());
        //不合格数量fiedQuantity
        qcResultCriteria.setFiedQuantity(qcRecord.getFiedQuantity());
        qcResultCriteria.setRemake(qcRecord.getRemake());
        //让步数量concessionQuantity
        qcResultCriteria.setConcessionQuantity(qcRecord.getConcessionQuantity());
        //检验时间qcTime
        qcResultCriteria.setQcTime(qcRecord.getQcTime());
        QcRecord newQcRecord = this.qcResult(qcResultCriteria, currentUser);
        //回传erp

        //
        AcceptRecord acceptRecord = acceptRecordService.getOneByField("accept_record_code", qcRecord.getAcceptRecordCode());
        String billId = acceptRecordService.billToErpNew(acceptRecord.getAsnBillNo(), newQcRecord);

        //erp审核回传
        //异步审核回传
    }

    /**
     * 全部合格
     * @param acceptRecord
     * @param currentUser
     */
    @Override
    @Transactional
    public void submitAll(AcceptRecord acceptRecord, CurrentUser currentUser) {
        QcResultCriteria qcResultCriteria = new QcResultCriteria();
        qcResultCriteria.setBillCode(acceptRecord.getAcceptRecordCode());
        qcResultCriteria.setQcResult(1);
        //合格数量  全部数量-已拣货数量-不合格数量 =合格数量
        qcResultCriteria.setQualifiedQuantity(acceptRecord.getQuantity()-acceptRecord.getQcQuantity()-acceptRecord.getUnqualifiedQuantity());
        //不合格数量fiedQuantity
        qcResultCriteria.setFiedQuantity(acceptRecord.getUnqualifiedQuantity());
        qcResultCriteria.setQcQuantity(acceptRecord.getQuantity() - acceptRecord.getQcQuantity());
        //让步数量concessionQuantity
        qcResultCriteria.setConcessionQuantity(0.0);
        //检验时间qcTime
        qcResultCriteria.setQcTime(DateUtils.getNowDateTimeString());
        QcRecord qcRecord = qcRecordService.qcResult(qcResultCriteria, currentUser);
        //回传erp
//       AcceptRecord acceptRecord = acceptRecordService.getOneByField("accept_record_code", criteria.getBillCode());
        String billId = acceptRecordService.billToErpNew(acceptRecord.getAsnBillNo(), qcRecord);
        //erp审核回传
    }

    /**
     * 不合格退料
     *
     * @param criteria
     * @return
     */
    @Override
    public List<QcRecordDto> findReturnList(QcRecordCriteria criteria) {
        return qcRecordMapper.findReturnList(criteria);
//        List<String> collect = returnList.stream().map(item -> item.getAcceptRecordCode()).collect(Collectors.toList());
//        List<RecordDto> recordDtos  =   acceptRecordService.findSupplierByCode(collect);
//        Map<String, RecordDto> recordDtoMap = convertMap(recordDtos, RecordDto::getAcceptRecordCode);
//        for (QcRecordDto qcRecordDto : returnList) {
//            RecordDto recordDto = recordDtoMap.get(qcRecordDto.getAcceptRecordCode());
//            if (ObjectUtil.isNotEmpty(recordDto)) {
//                qcRecordDto.setSupplierName(recordDto.getSupplierName());
//            }
//
//        }
    }

    @Autowired
    private PrintTempInfoService printTempInfoService;

    @Override
    public String allotPrint(String billNo, CurrentUser currentUser) {
        QcRecordCriteria qcRecordCriteria = new QcRecordCriteria();
        qcRecordCriteria.setQcRecordCode(billNo);
        List<QcRecordDto> returnList = qcRecordService.findReturnList(qcRecordCriteria);
        PrintTempInfo printTempInfo = printTempInfoService.getById(62);
        if (printTempInfo == null) {
            throw new ServiceException(CommonCode.SERVER_INERNAL_ERROR, "未匹配到验收标签模板");
        }
        String html = printTempInfo.getTempHtml();
        Document doc = Jsoup.parse(html);
        //删除不显示的
        doc.select(".dis-none").remove();
        //直线中间蓝点的问题
        doc.select(".line-handle").remove();
        doc.select(".baokuan").remove();
        Elements select = doc.select(".detail");
        Elements select1 = doc.select(".title");

        for (Element element : select) {
            System.out.println(element);
        }


        PrintTempUtils.setTempData("SHIP_BILL_NO", billNo, doc, "text");
        PrintTempUtils.setTempData("SHIP_BILL_NO_BAR_CODE", billNo, doc, "qrCode");
        PrintTempUtils.setTempData("PRINT_TIME", DateUtils.getNowDateTimeString(), doc, "text");
        PrintTempUtils.setTempData("PRINT_DATE", DateUtils.getNowDateString(), doc, "text");
        PrintTempUtils.setTempData("PRINT_USER_NAME", currentUser.getUserName(), doc, "text");
        if (doc.getElementById("FULL_ITEMS_DETAIL_TABLE") != null) {
            Element FULL_ITEMS_DETAIL_TABLE = doc.getElementById("FULL_ITEMS_DETAIL_TABLE");
            Element tbody = FULL_ITEMS_DETAIL_TABLE.getElementsByTag("tBody").get(0);
            Element ITEM_LIST_DETAIL = tbody.getElementById("ITEM_LIST_DETAIL");
            Integer colspan = 0;
            for (QcRecordDto qcRecord : returnList) {
                Element newEle = ITEM_LIST_DETAIL.clone();
                colspan += PrintTempUtils.setTempData("ITEM_CODE", qcRecord.getItemCode(), newEle, "text");
                colspan += PrintTempUtils.setTempData("ITEM_NAME", qcRecord.getItemName(), newEle, "text");
                colspan += PrintTempUtils.setTempData("BATCH_NAME", qcRecord.getBatchName(), newEle, "text");
                colspan += PrintTempUtils.setTempData("NOT_QC", qcRecord.getFiedQuantity(), newEle, "text");
                colspan += PrintTempUtils.setTempData("USER_NAME", qcRecord.getQcUserName(), newEle, "text");
                colspan += PrintTempUtils.setTempData("SUPPLIER_NAME",qcRecord.getSupplierName() , newEle, "text");
                newEle.appendTo(tbody);
            }

            ITEM_LIST_DETAIL.remove();
        }


        //doc在创建时里面包含了html head body等节点  不需要
        Element labelContent = doc.getElementsByAttributeValue("class", "label-content").get(0);
        String tempHtml = labelContent.toString();

        return tempHtml;
    }

    /**
     * 根据质检单生成库存事务
     *
     * @param qcRecord 质检单
     * @return InventoryTransact 库存事务
     */
    private InventoryTransact toStockRequest(QcRecord qcRecord, Integer result) {
        InventoryTransact inventoryTransact = new InventoryTransact();
        //Step1.准备数据
        //仓库
        inventoryTransact.setWareId(qcRecord.getWareId());
        inventoryTransact.setWareName(qcRecord.getWareName());
        //物料
        inventoryTransact.setItemCode(qcRecord.getItemCode());
        inventoryTransact.setItemName(qcRecord.getItemName());
        //批次
        inventoryTransact.setFromBatchId(qcRecord.getBatchId());
        inventoryTransact.setFromBatchName(qcRecord.getBatchName());
        //创建人 时间
        inventoryTransact.setCreateUserId(qcRecord.getQcUserId());
        inventoryTransact.setCreateUserName(qcRecord.getQcUserName());
        inventoryTransact.setCreateTime(DateUtil.now());
        //事务类型
        if (AsnManageConstant.QC_RESULT_UNQ.equals(result)) {
            //不合格 继续冻结 记录原因
            inventoryTransact.setTransactType(InventoryConstant.INVENTORY_FREEZE);
            inventoryTransact.setStateDis("不合格");
        } else {
            //合格 解冻
            inventoryTransact.setTransactType(InventoryConstant.INVENTORY_UNFREEZE);
        }

        //来源单据号
        inventoryTransact.setBillNo(qcRecord.getAsnBillNo());

        //Step2.保存，返回
        inventoryTransactService.save(inventoryTransact);
        return inventoryTransact;
    }

    /**
     * 生成质检单
     *
     * @param acceptRecord 收货单
     * @return QcRecord
     */
    private QcRecord processQcData(AcceptRecord acceptRecord) {
        QcRecord qcRecord = new QcRecord();
        //来源单号
        qcRecord.setAcceptRecordId(acceptRecord.getId());
        qcRecord.setAcceptRecordCode(acceptRecord.getAcceptRecordCode());
        //仓库
        qcRecord.setWareId(acceptRecord.getWareId());
        qcRecord.setWareName(acceptRecord.getWareName());
        //物料
        qcRecord.setItemCode(acceptRecord.getItemCode());
        qcRecord.setItemName(acceptRecord.getItemName());
        qcRecord.setPackDetailId(acceptRecord.getPackDetailId());
        qcRecord.setPackDescribe(acceptRecord.getPackDescribe());
        //批次
        qcRecord.setBatchId(acceptRecord.getBatchId());
        qcRecord.setBatchName(acceptRecord.getBatchName());
        //数量
        qcRecord.setQcQuantity(acceptRecord.getQuantity());

        return qcRecord;
    }

}
